import dalex as dx
import pandas as pd
import pickle
import xgboost as xgb
from sklearn.model_selection import train_test_split
input_df = pd.read_csv('preprocessed_dataset.csv')
y = input_df.loc[:,'Attrition']
X = input_df.drop('Attrition', axis='columns')
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=14)
model = pickle.load(open( "xgb_model.p", "rb" ))
explainer = dx.Explainer(model, X_train, y_train)
Preparation of a new explainer is initiated -> data : 7595 rows 24 cols -> target variable : Parameter 'y' was a pandas.Series. Converted to a numpy.ndarray. -> target variable : 7595 values -> model_class : xgboost.sklearn.XGBClassifier (default) -> label : Not specified, model's class short name will be used. (default) -> predict function : <function yhat_proba_default at 0x7f813c22f820> will be used (default) -> predict function : Accepts pandas.DataFrame and numpy.ndarray. -> predicted values : min = 9.37e-06, mean = 0.841, max = 1.0 -> model type : classification will be used (default) -> residual function : difference between y and yhat (default) -> residuals : min = -0.779, mean = -5.26e-05, max = 0.7 -> model_info : package xgboost A new explainer has been created!
Dla obserwacji 32. model przewiduje z prawie 100% prawdopodobieństwem, że klient nie zrezygnuje z usługi. W tym przypadku predykcja okazała się prawdziwa.
index = 32
display(explainer.predict(X_test)[index])
display(y_test.iloc[index])
0.9999609
1
def apply_lime_to_index(index):
display(explainer.predict(X_test)[index])
display(y_test.iloc[index])
ps = explainer.predict_surrogate(X_test.iloc[index,:], type='lime', seed=10)
ps.show_in_notebook()
ps.as_pyplot_figure()
apply_lime_to_index(32)
0.9999609
1
Pierwsze wyjaśnienie wykonałem bez zamknięcia kodu w funkcję, napisałem komentarz i przeszedłem do dalszych zadań. Drugi raz wyjaśniłem obserwację 32 po złożeniu kodu w jedną funkcję i po jej wykonaniu zauważyłem, że opis nie zgadza się z wynikami. Metoda LIME nie jest replikowalna, za każdym razem może dać inny wynik. Chyba, że ustawimy parametr seed, tak jak ja zrobiłem za 3 razem.
Wyjaśnienie lokalne metodą LIME dla obserwacji o indeksie 32 pokazuje, że spośród 10 najbardziej wpływających na predykcję zmiennych, 9 przyczynia się do zwiększenia prawdopodobieństwa, że wynik będzie równy 1, a tylko jedna, Months_on_book (liczba miesięcy jako klient), ujemnie kontrybuuje.
Wyjaśnienie lokalne metodą LIME dla obserwacji o indeksie 32 pokazuje, że spośród 10 najbardziej wpływających na predykcję zmiennych, 9 przyczynia się do zwiększenia prawdopodobieństwa, że wynik będzie równy 1, a tylko jedna, Card_Silver (liczba miesięcy jako klient), ujemnie kontrybuuje.
Wyjaśnienie lokalne metodą LIME dla obserwacji o indeksie 32 pokazuje, że spośród 10 najbardziej wpływających na predykcję zmiennych, wszystkie przyczyniają się do zwiększenia prawdopodobieństwa, że wynik będzie równy 1.
apply_lime_to_index(22)
0.9954454
1
Dla obserwacji o indeksie 22 predykcja też jest bardzo bliska 1. Mimo tego metoda LIME wskazuje, że 4 z 10 zmiennych zbliżało predykcję do 0. Czynnik który ma najwiekszy wpływ, Card_Platimum <= 0, ma duży współczynnik w porównaniu ze współczynnikami z pierwszej analizy obserwacji 32. Podobnie Total_Ct_Chng_Q4_Q1 <= 0.58 (zmiana liczby transakcji pomiędzy kwartałami) ma duży współczynnik, z tym że ujemny.
apply_lime_to_index(55)
0.98524845
1
W tym przypadku fakt, że Card_Platinum <= 0 ujemnie wpływa na predykcję. Jego wpływ jest odwrotny niż w przypadku poprzedniej obserwacji (o indeksie 22). Wśród zmiennych o największym znaczeniu są 3 zmienne kodujące typ karty (Platinum, Gold, Silver).
apply_lime_to_index(6)
0.007773618
0
W tym przypadku widzimy wyjaśnienie, gdy model przewidział wynik 0. Tę samą obserwację przeanalizowano metodą break down w pracy domowej 1. Najbardziej znaczące zmienne są inne (LIME: Total_Revolving_Bal, Total_Ct_Chng_Q4_Q1, BREAK DOWN: Total_Amt_Chng_Q4_Q1, Contacts_Count_12_mon).
Skupmy się na wartościach Total_Revolving_Bal. Ta cecha pojawia się we wszystkich powyższych wyjaśnieniach. Wartości tej ciągłej zmiennej zostały podzielone na przedziały. Jej kontrybucja zmienia się w zależności od tego w jakim przedziale występuje wartość. Jeśli Total_Revolving_Bal > 1782, to przyczynia się do wyniku predykcji 1 (dzieje się tak dla obserwacji z indeksem 55 oraz 32). Jeśli 457.5 < Total_Revolving_Bal <= 1782, to jej kontrybucja jest nadal pozytywna, ale mniejsza. Natomiast jeśli 457.5 <= Total_Revolving_Bal, to wpływ jest ujemny.
as_pyplot_figure() umieszcza całe nazwy zmiennych na wykresie wraz z przedziałami dyskretyzacji metody LIME.